using System;
using System.Collections.Generic;
using System.Text;
using TgcViewer.Utils.TgcKeyFrameLoader;
using TgcViewer;
using Microsoft.DirectX;
using Microsoft.DirectX.DirectInput;
using AlumnoEjemplos.TP3D.Acciones;
using Microsoft.DirectX.Direct3D;
using AlumnoEjemplos.TP3D.Collider;

namespace AlumnoEjemplos.TP3D
{
    public class Mario : Placeable
    {
        public static readonly float VELOCIDAD_ROTACION_INCIAL = 0f;
        public static readonly Vector3 MOVIMIENTO_NULO = new Vector3();

        public static readonly Vector3 VELOCIDAD_CAIDA = new Vector3(0, -3, 0);
        public static readonly Vector3 VELOCIDAD_SALTO = new Vector3(0, 5, 0);
        Vector3 saltozqui = new Vector3();

        EstadoMario estado = null;

        TgcKeyFrameMesh mesh;
        string caminar = "Animation";
        string saltar = "Jump";
        string parate = "Parado";

        Vector3 _velocidadCaminar = new Vector3(0, 0, 60f);
        float _velocidadRotacion = 120f;

        public Vector3 VelocidadCaminar
        {
            get
            {
                return _velocidadCaminar;
            }
            set
            {
                this._velocidadCaminar = value;
            }
        }

        public virtual EstadoMario Estado
        {
            get { return estado; }
            set { estado = value; }
        }

        public float VelocidadRotacion
        {
            get
            {
                return _velocidadRotacion;
            }
            set
            {
                this._velocidadRotacion = value;
            }
        }

        ICollection<Accion> acciones = new List<Accion>();

        Vector3 _velocidad = new Vector3();
        float _rotacion = 0f;

        public Vector3 Velocidad
        {
            get { return _velocidad; }
            set { _velocidad = value; }
        }

        public float Rotacion
        {
            get { return _rotacion; }
            set { _rotacion = value; }
        }

        public Mario()
        {
            LoadMario();

            this.estado = new EnElPiso();

            acciones.Add(new Avanza(Key.W));
            acciones.Add(new RotaIzquierda(Key.A));
            acciones.Add(new RotaDerecha(Key.D));
            acciones.Add(new Retrocede(Key.S));
            acciones.Add(new Salto(Key.Space));
        }

        private void LoadMario()
        {
            string rootPath = GuiController.Instance.ExamplesMediaDir + "KeyframeAnimations\\Mario\\";
            string extensionNombreAnimacion = "-TgcKeyFrameAnim.xml";
            string nombreModelo = "Mario";
            string extensionNombreModelo = "-TgcKeyFrameMesh.xml";

            TgcKeyFrameLoader keyFrameLoader = new TgcKeyFrameLoader();
            mesh = keyFrameLoader.loadMeshAndAnimationsFromFile(
                rootPath + nombreModelo + extensionNombreModelo,
                rootPath,
                new string[] { 
                    rootPath + caminar + extensionNombreAnimacion,
                    rootPath + parate + extensionNombreAnimacion,
                    rootPath + saltar + extensionNombreAnimacion
                });
        }

        public virtual TgcKeyFrameMesh Mesh
        {
            get
            {
                return mesh;
            }
        }

        public virtual Vector3 Position
        {
            get
            {
                return mesh.Position;
            }
        }

        #region animaciones

        public virtual void DoAnimacionParate()
        {
            Mesh.playAnimation(parate, true);
        }

        public virtual void DoAnimacionSalto()
        {
            Mesh.playAnimation(saltar, true);
        }

        public virtual void DoAnimacionCaminar()
        {
            Mesh.playAnimation(caminar, true);
        }

        #endregion animaciones

        public virtual void HandleInput()
        {
            foreach (Accion a in acciones)
            {
                a.AplicateA(this);
            }
        }

        private bool EstaCayendo(Vector3 velocidadSalto)
        {
            return velocidadSalto == VELOCIDAD_CAIDA && Mesh.Position.Y > -45;
        }

        private bool EstaEnElAire()
        {
            return Mesh.Position.Y > -45;
        }

        public virtual void Avanza()
        {
            this.estado.Avanza(this);
        }

        public virtual void Retrocede()
        {
            this.estado.Retrocede(this);
        }

        public void RotaIzquierda()
        {
            this._rotacion -= this._velocidadRotacion;
        }

        public void RotaDerecha()
        {
            this._rotacion += this._velocidadRotacion;
        }

        public void Salta()
        {
            this.estado.Salta(this);
        }

        public virtual void Render()
        {
            Mesh.animateAndRender();
        }

        public virtual void Init()
        {
            this.estado.Init(this);
        }

        public bool HasRotation
        {
            get
            {
                return VELOCIDAD_ROTACION_INCIAL != this._rotacion;
            }
        }

        public bool HasMoved
        {
            get
            {
                return MOVIMIENTO_NULO != this._velocidad;
            }
        }

        public bool EstasEnElPiso()
        {
            return Mesh.Position.Y <= -45;
        }

        internal void MoveTo(Vector3 vector3)
        {
            this._velocidad = vector3;
        }

        public void Update(float elapsedTime)
        {
            this.estado.Update(this, elapsedTime);
        }
    }
}
